﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using log4net;

namespace Dazzle {
    /// <summary>
    /// Matlab画图函数库
    /// </summary>
    internal class DrawLib {
        /// <summary>
        /// singleton
        /// </summary>
        private static DrawLib _instance;

        // Draw libarary root directory.
        private static readonly string DRAW_LIB_ROOT = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DrawLib");
        
        private static ILog logger = LogManager.GetLogger(typeof(DrawLib));
        private Hashtable _drawlibTable = null;

        /// <summary>
        /// The private constructor for load all matlab functions.
        /// </summary>
        private DrawLib() {
            if (Directory.Exists(DRAW_LIB_ROOT)) {
                string[] drawFiles = Directory.GetFiles(DRAW_LIB_ROOT, "*.dll");

                _drawlibTable = new Hashtable(drawFiles.Length);

                foreach (string df in drawFiles) {
                    string drawFuncName = Path.GetFileNameWithoutExtension(df);

                    string cls = string.Format("MatlabDraw.{0}.Mat{0}", drawFuncName);

                    try {
                        Assembly assembly = Assembly.LoadFile(df);
                        object funcCls = assembly.CreateInstance(cls, true);

                        if (funcCls == null) {
                            logger.Error("Can't create instance of draw func {0}, The assembly file is {1}", cls, df);
                        } else {
                            _drawlibTable[drawFuncName] = funcCls;
                        }
                    }catch(Exception ex){
                        logger.Error(string.Format("Can't create instance of draw func {0}, The assembly file is {1}", cls, df),
                            ex);

                        throw ex;
                    }
                }
            } else {
                _drawlibTable = new Hashtable(0);
                logger.Warn("DrawLib {0} is not exists.", DRAW_LIB_ROOT);
            }
        }

        /// <summary>
        /// Get the draw lib instance.
        /// </summary>
        public static DrawLib Instance {
            get {
                if (_instance == null) {
                    _instance = new DrawLib();
                }

                return _instance;
            }
        }

        /// <summary>
        /// Get the matlab draw function with function name.
        /// </summary>
        /// <exception cref="ArgumentNullException">The exception will be occured, while the funcName argument is null or empty</exception>
        /// <param name="funcName">The function name</param>
        /// <returns></returns>
        public object GetDrawFunc(string funcName) {
            if (string.IsNullOrEmpty(funcName))
                throw new ArgumentNullException("funcName", "FuncName must be not null or emtpy.");

            return _drawlibTable[funcName];
        }

        /// <summary>
        /// Get the names of all the functions.
        /// </summary>
        /// <returns></returns>
        internal ICollection GetAllFuncNames() {
            return _drawlibTable.Keys;
        }
    }
}
